Imports OpenArchive.System.DB.Tables
Imports System.Xml.Serialization
Imports OpenArchive.System
Imports OpenArchive.Document
Imports OpenArchive.Collections

Namespace OpenArchive

    <Reflection.DefaultMember("Item")> _
    Public Class Archive
        Implements IEnumerable

        Private m_Name As String
        Private m_Count As Long
        Private m_root As String
        Private m_Location As String
        Private m_DataproviderInstance As DB.IArchiveDataProvider
        Private m_Settings As ArchiveSettings
        Private Const c_ArchiveSettingsFileName As String = "archive.config"
        Private m_synclock As Object
        'Icons '16, 24, 32, 48, 64 oder 128 pixel
        Public Sub New(ByVal Name As String)
            Me.New(Name, Nothing)
        End Sub
        Public Sub New(ByVal Name As String, ByVal Location As String)
            m_DataproviderInstance = Activator.CreateInstance(OpenArchive.System.ArchiveSystem.DataProvider)
            If Not String.IsNullOrEmpty(Location) Then
                m_Location = Location
                m_Settings = LoadSettings()
            End If
            ' ToDo Check Exsistens
            ' ToDo LoadSettings
            m_Name = Name
        End Sub
        Public Property Settings() As ArchiveSettings
            Get
                If m_Settings Is Nothing Then
                    Return LoadSettings()
                End If
            End Get
            Set(ByVal value As ArchiveSettings)
                If Not value.Equals(m_Settings) Then
                    ' Save new Settings
                    SaveSettings(value)
                End If
            End Set
        End Property
        Public Function Update(ByVal document As Document.Document)
            ' Add new components
            ' Check changes in components
        End Function
        Public Sub Add(ByVal document As Document.Document)

            If document.ID > 0 Then
                Update(document)
            End If

            Dim _doctableentry As DB.Tables.DocTable = New DB.Tables.DocTable()
            _doctableentry.DocType = document.GetType().Name
            _doctableentry.VolumeID = 0
            _doctableentry.Created = Date.Now
            _doctableentry.Deleted = False


            If m_synclock Is Nothing Then m_synclock = New Object

            SyncLock m_synclock
                Dim _id As Long = m_DataproviderInstance.AddDocTableEntry(Me, _doctableentry, m_Location)
                document.ArchiveProperties.ID = _id
            End SyncLock

            Dim _dirsep As Char = Global.System.IO.Path.DirectorySeparatorChar

            'Dim _writetoDocTyble As Generic.Dictionary(Of Long, DB.Tables.DocTable)
            '_writetoDocTyble = New Generic.Dictionary(Of Long, DB.Tables.DocTable)

            For Each _InstanceComponentpair As InstanceComponentPair(Of Integer, Components.IComponent) In document
                Dim _datacomponent As Components.Data.IComponentData
                _datacomponent = _InstanceComponentpair.Component.DataObjects
                ' Find Formatter for this data component
                Dim Formatter As OpenArchive.Formatters.IComponentFormatter
                Formatter = OpenArchive.System.ArchiveSystem.System.GetFormatter(_datacomponent)
                If Not Formatter Is Nothing Then
                    Dim _filepath As String = m_Location & _dirsep & Archives.c_WriteCacheDir & _dirsep & document.ID.ToString("X16") & "." & _InstanceComponentpair.Instance.ToString("D2") & "." & _datacomponent.GetType().Name

                    Dim _file As New IO.FileStream(_filepath, Global.System.IO.FileMode.CreateNew)
                    Formatter.Serialize(_file, _datacomponent)
                    Dim _size As Long = _file.Length
                    _file.Close()
                    _file.Dispose()
                    'Update DocTable
                    Dim _compTableEntry As DB.Tables.CompTable = New DB.Tables.CompTable()
                    _compTableEntry.Name = _datacomponent.GetType().Name
                    _compTableEntry.Offset = 0
                    _compTableEntry.Size = _size
                    _compTableEntry.Version = _datacomponent.Version
                    _compTableEntry.Instance = _InstanceComponentpair.Instance
                    _doctableentry.AddComponentEntry(_compTableEntry)
                End If
            Next
            Try
                SyncLock m_synclock
                    m_DataproviderInstance.UpdateDocTableEntry(Me, document.ID, _doctableentry, m_Location)
                End SyncLock
            Catch ex As Exception
                ' try to delete all written files
                For Each _InstanceComponentpair As InstanceComponentPair(Of Integer, Components.IComponent) In document
                    'Dim _filepath As String = m_Location & _dirsep & Archives.c_WriteCacheDir & _dirsep & document.ID.ToString("X16") & "." & _InstanceComponentpair.Instance.ToString("D2") & "." & _datacomponent.GetType().Name
                    Try
                        'Global.System.IO.File.Delete(_filepath)
                    Catch ex1 As Exception

                    End Try
                    Throw New Global.System.Exception("Can't archive document", ex)
                Next
            End Try
        End Sub
        Friend Sub StartStoreprocess()
            Dim _awaitingdoctabs As DB.Tables.DocTable()
            _awaitingdoctabs = m_DataproviderInstance.GetDocTableEntries(Me, 0, m_Location)

            For Each _doctab As DB.Tables.DocTable In _awaitingdoctabs
                Try
                    'AddToActiveVolume(_doctab)
                Catch ex As Exception

                End Try
            Next

            ' Dim _id As Long = m_DataproviderInstance.AddDocTableEntry(Me, _doctableentry, m_Location)
        End Sub
        Private Function GetActiveVolume() As Long

        End Function
        Public Function Search(ByVal index As Components.IndexComponent) As List(Of Document.Document)


        End Function
        'Public ReadOnly Property Volumes() As Volumes
        '    Get

        '    End Get
        'End Property
        Public ReadOnly Property Name() As String
            Get
                Return m_Name
            End Get
        End Property
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <value></value>
        ''' <returns>Returns the number of documents</returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Count() As Long
            Get
                Return m_DataproviderInstance.GetDocTableCount(Me, Location)
            End Get
        End Property
        Public Sub ReadComponentData(ByVal sender As Object, ByVal eventargs As System.Events.ReadEventArguments)
            Dim _doctableentry As DB.Tables.DocTable
            _doctableentry = m_DataproviderInstance.GetDocTableEntry(Me, eventargs.Document.ID, m_Location)
            Dim _dirsep As Char = Global.System.IO.Path.DirectorySeparatorChar
            Dim _comptable As DB.Tables.CompTable
            Dim _responsibleCompTableEntries As List(Of CompTable) = New List(Of CompTable)
            Dim _CompDatas As List(Of Components.Data.IComponentData) = New List(Of Components.Data.IComponentData)

            For Each _comptable In _doctableentry.Components
                Dim _comptype As Type = OpenArchive.System.Utils.GetTypeByName(_comptable.Name)
                If eventargs.Component.IsResponsible(_comptype, _comptable.Version) Then
                    _responsibleCompTableEntries.Add(_comptable)
                End If
            Next

            For Each _comptable In _responsibleCompTableEntries
                Dim _compdatatype As Type = OpenArchive.System.Utils.GetTypeByName(_comptable.Name)
                Dim _formatter As OpenArchive.Formatters.IComponentFormatter
                _formatter = OpenArchive.System.ArchiveSystem.System.GetFormatter(_compdatatype, _comptable.Version)
                If Not _formatter Is Nothing Then
                    Dim _filepath As String = m_Location & _dirsep & Archives.c_WriteCacheDir & _dirsep & eventargs.Document.ID.ToString("X16") & "." & _comptable.Instance.ToString("D2") & "." & _comptable.Name
                    Dim _filestream As IO.FileStream = Nothing
                    Try
                        _filestream = New IO.FileStream(_filepath, Global.System.IO.FileMode.Open)
                        Dim _compdata As Components.Data.ComponentData = _formatter.Deserialize(_filestream)
                        _filestream.Close()
                        _filestream.Dispose()
                        _CompDatas.Add(_compdata)
                    Catch ex As Exception
                        If Not _filestream Is Nothing Then
                            _filestream.Close()
                            _filestream.Dispose()
                        End If
                    End Try
                End If
            Next
            If _CompDatas.Count = 1 Then
                eventargs.Component.DataObjects = _CompDatas(0)
            Else
                'eventargs.Component.DataObjects = _CompDatas.ToArray
            End If


        End Sub
        Default Public Overloads ReadOnly Property Item(ByVal id As Long) As Document.Document
            Get
                Dim _doctableentry As DB.Tables.DocTable
                _doctableentry = m_DataproviderInstance.GetDocTableEntry(Me, id, m_Location)

                Dim _dirsep As Char = Global.System.IO.Path.DirectorySeparatorChar

                If Not _doctableentry Is Nothing Then
                    Dim _document As Document.Document
                    Dim _doctype As Type
                    _doctype = System.Utils.GetTypeByName(_doctableentry.DocType)

                    _document = Runtime.Serialization.FormatterServices.GetUninitializedObject(_doctype)

                    Dim _archprops As Document.ArchiveProperties = New Document.ArchiveProperties()
                    _archprops.ID = id
                    _archprops.Archive = Me
                    _document.ArchiveProperties = _archprops

                    Dim _complist As ComponentList = New ComponentList(_document)

                    For Each _comptable As CompTable In _doctableentry.Components
                        Dim _compdatatype As Type
                        _compdatatype = System.Utils.GetTypeByName(_comptable.Name)
                        Dim _component As Components.IComponent
                        _component = OpenArchive.System.ArchiveSystem.System.GetComponent(_compdatatype, _comptable.Version)
                        _component.DataObjects = Nothing
                        _complist.Add(_comptable.Instance, _component)
                    Next
                    _document.m_componentlist = _complist
                    AddHandler _document.m_componentlist.ReadComponentRequested, AddressOf ReadComponentData
                    Return _document
                End If
                Return Nothing
            End Get
        End Property
        Public Property DataProviderInstance() As DB.IArchiveDataProvider
            Get
                Return m_DataproviderInstance
            End Get
            Set(ByVal value As DB.IArchiveDataProvider)
                m_DataproviderInstance = value
            End Set
        End Property
        Friend Property Location() As String
            Get
                Return m_Location
            End Get
            Set(ByVal value As String)
                m_Location = value
            End Set
        End Property
        Private Function LoadSettings() As ArchiveSettings
            Dim _dirsep As Char = Global.System.IO.Path.DirectorySeparatorChar
            Dim serializer As New XmlSerializer(GetType(ArchiveSettings))
            Dim reader As New Global.System.IO.StreamReader(Location & _dirsep & c_ArchiveSettingsFileName)
            Return serializer.Deserialize(reader)
        End Function
        Private Sub SaveSettings(ByVal ArchSettings As ArchiveSettings)
            Dim _dirsep As Char = Global.System.IO.Path.DirectorySeparatorChar
            Dim serializer As New XmlSerializer(GetType(ArchiveSettings))
            Dim writer As New Global.System.IO.StreamWriter(Location & _dirsep & c_ArchiveSettingsFileName)
            serializer.Serialize(writer, ArchSettings)
            writer.Dispose()
            writer.Close()
        End Sub
        Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator

        End Function
    End Class



End Namespace

